/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.generator;

/**
 *
 * @author Laurent WOUTERS
 */
public class Application {
    public static void main(String[] args) {
        xowl.utils.logging.Logger log = new xowl.utils.logging.Logger(Application.class.getName(), org.apache.log4j.Level.INFO);
        if (args.length == 0) {
            log.fatal(Application.class.getName(), "No config file in parameters");
            return;
        }
        xowl.utils.config.Configuration config = new xowl.utils.config.Configuration();
        try { config.load(args[0]); }
        catch (java.io.IOException ex) {
            log.fatal(Application.class.getName(), "Failed to load configuration file: " + args[0], ex);
            return;
        }
        xowl.generator.Application app = new xowl.generator.Application(log, config);
        app.run();
    }

    private xowl.utils.logging.Logger log;
    private String interpreterLibsPath;
    private java.util.List<InputSource> inputSources;
    private java.util.Map<InputSource, String> inputReferences;
    private java.util.List<String> inputRefJars;
    private String inputRepository;
    private String inputBasePackage;
    private boolean debug;
    private GenerationMode outputMode;
    private String outputDirectory;
    private String outputJarName;
    private int outputMaxFileLength;
    
    public String getInterpreterLibsPath() { return interpreterLibsPath; }
    public void setInterpreterLibsPath(String path) { interpreterLibsPath = path; }
    public java.util.List<InputSource> getSources() { return inputSources; }
    public java.util.Map<InputSource, String> getReferences() { return inputReferences; }
    public java.util.List<String> getReferenceJars() { return inputRefJars; }
    public String getRepository() { return inputRepository; }
    public void setRepository(String repo) { inputRepository = repo; }
    public String getBasePackage() { return inputBasePackage; }
    public void setBasePackage(String basePackage) { inputBasePackage = basePackage; }
    public boolean isDebug() { return debug; }
    public void setDebug(boolean debug) { this.debug = debug; }
    public GenerationMode getGenerationModel() { return outputMode; }
    public void setGenerationMode(GenerationMode mode) { outputMode = mode; }
    public String getOutputDirectory() { return outputDirectory; }
    public void setOutputDirectory(String dir) { outputDirectory = dir; }
    public String getJarName() { return outputJarName; }
    public void setJarName(String name) { outputJarName = name; }
    
    public int getMaxFileLength() { return outputMaxFileLength; }
    
    public Application(xowl.utils.logging.Logger log, xowl.utils.config.Configuration config) {
        this.log = log;
        this.interpreterLibsPath = "";
        this.inputSources = new java.util.ArrayList<InputSource>();
        this.inputReferences = new java.util.HashMap<InputSource, String>();
        this.inputRefJars = new java.util.ArrayList<String>();
        this.debug = false;
        this.outputMode = GenerationMode.Native;
        this.outputJarName = "Model";
        this.outputMaxFileLength = 100;
        loadConfig(config);
    }

    private void loadConfig(xowl.utils.config.Configuration config) {
        String value = config.getValue("libs");
        if (value != null)
            interpreterLibsPath = value;

        value = config.getValue("repository");
        if (value != null)
            inputRepository = value;

        java.util.List<String> values = config.getValues(null, "input");
        for (String val : values) {
            String[] parts = val.split("\\|");
            InputSource input = new InputSource();
            input.source = parts[0].trim();
            input.type = xowl.interpreter.OWL2Syntax.valueOf(parts[1].trim());
            inputSources.add(input);
        }

        values = config.getValues(null, "reference");
        for (String val : values) {
            String[] parts = val.split("\\|");
            InputSource input = new InputSource();
            input.source = parts[0].trim();
            input.type = xowl.interpreter.OWL2Syntax.valueOf(parts[1].trim());
            String jar = parts[2].trim();
            inputReferences.put(input, parts[3]);
            if (!inputRefJars.contains(jar))
                inputRefJars.add(jar);
        }
        
        value = config.getValue("basePackage");
        if (value != null)
            inputBasePackage = value;

        value = config.getValue("debug");
        if (value != null)
            debug = Boolean.valueOf(value);
        
        value = config.getValue("mode");
        if (value != null)
            outputMode = GenerationMode.valueOf(value);

        value = config.getValue("output");
        if (value != null)
            outputDirectory = value;

        value = config.getValue("jarName");
        if (value != null)
            outputJarName = value;

        value = config.getValue("maxFileLength");
        if (value != null)
            outputMaxFileLength = java.lang.Integer.parseInt(value);
    }

    public void run() {
        java.lang.System.setProperty("user.lib", outputDirectory);
        java.lang.System.out.println("-- Loading ontology repository");

        xowl.interpreter.Interpreter.config(log, interpreterLibsPath);
        xowl.interpreter.Repository repo = xowl.interpreter.Interpreter.createRepositoryNative(log);
        xowl.generator.ModelGenerator model = new ModelGenerator(this, repo, inputBasePackage);
        
        for (InputSource source : inputSources)
            repo.loadOntology(inputRepository + source.source, source.type);
        for (InputSource source : inputReferences.keySet()) {
            xowl.lang.owl2.Ontology onto = repo.loadOntology(inputRepository + source.source, source.type);
            model.addReference(onto, inputReferences.get(source));
        }
        model.load();
        
        
        java.lang.System.out.println("-- Generating java code");
        model.build();
        try { model.write(outputDirectory, outputMode); }
        catch (Exception ex) { log.fatal(Application.class.getName(), ex.getMessage(), ex); }

        try {
            xowl.generator.builder.Builder builder = new xowl.generator.builder.Builder(outputDirectory, debug);
            for (String library : inputRefJars) {
                builder.addLibrary(library);
                xowl.interpreter.Interpreter.loadLibraries(new String[] {library});
            }
            builder.build(outputJarName);
        }
        catch (Exception ex) { log.fatal(Application.class.getName(), ex.getMessage(), ex); }
        java.lang.System.out.println("-- Done");
    }
}
